#include "in.h"

int MDBSelect( struct MemTable *table , void *select_record , ... )
{
	va_list				valist ;
	struct MemField			select_field_array[ MDB_PARSE_SELECT_FIELD_ARRAY_MAXCOUNT ] ;
	size_t				select_field_array_count ;
	size_t				select_field_array_no ;
	void				*where_record = NULL ;
	struct MemField			where_field_array[ MDB_PARSE_WHERE_FIELD_ARRAY_MAXCOUNT ] ;
	size_t				where_field_array_count ;
	
	struct MemIndex			*index = NULL ;
	
	struct MemIndexDataUnit		*index_dataunit = NULL ;
	char				*record_dataunit = NULL ;
	char				*record_data = NULL ;
	
	int				nret = 0 ;
	
	va_start( valist , select_record );
	
	nret = ConvertArgsToArray( valist , select_field_array , sizeof(select_field_array)/sizeof(select_field_array[0]) , & select_field_array_count ) ;
	if( nret )
	{
		TRACE_PRINTF( "ConvertArgsToArray select fields failed[%d]\n" , nret );
		return nret;
	}
	else
	{
		TRACE_PRINTF( "ConvertArgsToArray select fields ok\n" );
	}
	
	where_record = va_arg( valist , void* ) ;
	
	nret = ConvertArgsToArray( valist , where_field_array , sizeof(where_field_array)/sizeof(where_field_array[0]) , & where_field_array_count ) ;
	if( nret )
	{
		TRACE_PRINTF( "ConvertArgsToArray where fields failed[%d]\n" , nret );
		return nret;
	}
	else
	{
		TRACE_PRINTF( "ConvertArgsToArray where fields ok\n" );
	}
	
	va_end( valist );
	
	CreateCurrentTransaction( table->db );
	
	index = QueryExecuteSchedule( table , where_field_array , where_field_array_count ) ;
	if( index )
	{
		TRACE_PRINTF( "QueryExecuteSchedule return index->index_name[%s]\n" , index->index_name );
		
		index_dataunit = QueryIndexDataUnitTreeNode( where_record , index , where_field_array , where_field_array_count ) ;
		if( index_dataunit == NULL )
		{
			TRACE_PRINTF( "QueryIndexDataUnitTreeNode return NULL , throw SQL_NOT_FOUND\n" );
			DestroyCurrentTransaction( table->db );
			return (tls_last_errno=MDB_INFO_SQL_NOT_FOUND);
		}
		else
		{
			TRACE_PRINTF( "QueryIndexDataUnitTreeNode return record[%p]\n" , index_dataunit );
		}
		
		record_dataunit = index_dataunit->record_dataunit ;
	}
	else
	{
		TRACE_PRINTF( "QueryExecuteSchedule return no index\n" );
		record_dataunit = QueryFirstRecordWithoutIndex( table , where_record , where_field_array , where_field_array_count ) ;
		if( record_dataunit == NULL )
		{
			TRACE_PRINTF( "QueryFirstRecordWithoutIndex return NULL , throw SQL_NOT_FOUND\n" );
			DestroyCurrentTransaction( table->db );
			return (tls_last_errno=MDB_INFO_SQL_NOT_FOUND);
		}
		else
		{
			TRACE_PRINTF( "QueryFirstRecordWithoutIndex return record[%p]\n" , record_dataunit );
		}
	}
	
	record_data = MDB_RECORD_DATAUNIT_TO_DATA(record_dataunit) ;
	for( select_field_array_no = 0 ; select_field_array_no < select_field_array_count ; select_field_array_no++ )
	{
		memcpy( select_record+select_field_array[select_field_array_no].field_offset , record_data+select_field_array[select_field_array_no].field_offset , select_field_array[select_field_array_no].field_size );
		TRACE_PRINTF( "memcpy record[%p][%p] out .field_offset[%d] .field_size[%zu] " , record_dataunit , record_data , select_field_array[select_field_array_no].field_offset , select_field_array[select_field_array_no].field_size ); TRACE_PRINTHEX( select_record , select_field_array[select_field_array_no].field_size ); TRACE_PRINTEOL();
	}
	
	DestroyCurrentTransaction( table->db );
	
	return 0;
}

